package com.magnate.software.spring.boot.web.aop;

import com.magnate.software.common.mybatis.context.PagingContextHolder;
import com.magnate.software.common.mybatis.domain.Page;
import com.magnate.software.spring.boot.web.anotation.EnablePaging;
import com.magnate.software.spring.boot.web.page.QueryPage;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.lang.reflect.Method;

/**
 * 分页切面
 *
 * @author WangYang
 * @version 1.0
 * @datetime 2017/3/1 10:56
 */
@Aspect
@Service("pageAspect")
public class PageAspect {

    private static final Logger logger = LoggerFactory.getLogger(PageAspect.class);

    @Pointcut("execution(public * com.magnate.software.spring.boot.web.controller.*.*(..))")
    public void pagePointcut() {

    }

    @Before("pagePointcut()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        logger.info("方法AOP开始时间：" + System.currentTimeMillis());
        try {
            Signature signature = joinPoint.getSignature();
            MethodSignature methodSignature = (MethodSignature) signature;
            Object target = joinPoint.getTarget();
            Method method = target.getClass().getMethod(methodSignature.getName(), methodSignature.getParameterTypes());


            // 判断是否是带有翻页注解
            if (method.isAnnotationPresent(EnablePaging.class)) {
                checkEnablePaging(joinPoint.getArgs());
            }
        } catch (Throwable t) {
            logger.debug("翻页方法处理异常！", t);
            throw t;
        }
    }

    private void checkEnablePaging(Object[] args) throws Throwable {
        // 查找方法中是否有翻页参数
        for (Object obj : args) {
            if (QueryPage.class.isInstance(obj)) {
                QueryPage queryPage = (QueryPage) obj;
                // 设置翻页参数
                addContextHolder(getPage(queryPage));
                break;
            }
        }
    }

    /**
     * 获得翻页参数对象
     *
     * @param queryPage Query翻页参数
     * @return
     */
    protected Page getPage(QueryPage queryPage) {
        logger.info("EnablePaging QueryPage Params nextId：" + queryPage.getNextId() + " page：" + queryPage.getPage());
        Page rollPage = new Page();
        //当前页
        Integer page = queryPage.getPage();
        int currentPage = (page != null && page > 0 ? page : 1);
        rollPage.setCurrentPage(currentPage);
        logger.debug("当前页数：[" + currentPage + "]");
        //每页显示条数
        Integer rows = queryPage.getCount();
        int pageSize = (rows != null && rows > 0 ? rows : 10);
        rollPage.setPageSize(pageSize);
        logger.debug("当前页显示条数：[" + pageSize + "]");
        return rollPage;
    }

    public void addContextHolder(Page rollPage) {
        // 设置翻页参数
        PagingContextHolder.setPage(rollPage);
    }

    public void clearContextHolder() {
        // 清理过期的翻页参数
        PagingContextHolder.removePage();
    }

    @AfterReturning(value = "pagePointcut()", returning = "ret")
    public void doAfterReturning(Object ret) throws Throwable {
        // 处理完请求，返回内容
        logger.info("方法AOP返回值：" + ret);
        logger.info("方法AOP结束时间：" + System.currentTimeMillis());
        // 清理翻页参数
        clearContextHolder();
    }

}
